#include "fml_config.h"

#define SW_VERSION_MAIN     1
#define SW_VERSION_SUB      0
#define SW_VERSION_REVISE   0

#define OTA_INFO_KEY    "ota_info"
#define DEV_INFO_KEY    "dev_info"

DEV_INFO g_dev_info;
cJSON *g_dev_info_json = NULL;

int32_t fml_config_init(void)
{
    cJSON *p_root = NULL;
    cJSON *p_item = NULL;
    uint8_t *str_buff = NULL;
    uint8_t *json_cfg = NULL;
    int32_t ret = 0;

    memset(&g_ota_info, 0, sizeof(g_ota_info));
    memset(&g_dev_info, 0, sizeof(g_dev_info));
    
    g_dev_info.software_version[0] = SW_VERSION_MAIN;
    g_dev_info.software_version[1] = SW_VERSION_SUB;
    g_dev_info.software_version[2] = SW_VERSION_REVISE;
    
    str_buff = (uint8_t *)malloc(FLASH_PAGE_SIZE);
    if (str_buff == NULL)
        return -1;
    
    hal_flash_read(str_buff, CONFIG_START_ADDR, CONFIG_SIZE);
    
    printf("Config Json:%s\r\n", str_buff);
    
    ret = fml_config_from_json(str_buff, &g_dev_info, &g_ota_info);
    if (ret == -2)
    {
        json_cfg = fml_config_to_json(&g_dev_info, &g_ota_info);
        if (json_cfg)
        {
            hal_flash_erase(CONFIG_START_ADDR, CONFIG_SIZE);
            hal_flash_write(json_cfg, CONFIG_START_ADDR, CONFIG_SIZE);
        }
    }
    
    if (str_buff)
        free(str_buff);
    
    return ret;
}

int32_t fml_config_json_to_devinfo(DEV_INFO *dev_info, cJSON *p_root)
{
    cJSON *p_item = NULL;
    uint8_t version[3] = {0};
    
    if ((dev_info == NULL) || (p_root == NULL))
        return -1;
    
    p_item = cJSON_GetObjectItem(p_root, "dev_addr");
    if (NULL == p_item)
    {
        printf("Get software_version item failed\r\n");
        return -2;
    }
    dev_info->dev_addr = p_item->valueint;
    
    //p_item = cJSON_GetObjectItem(p_root, "software_version");
    //if (NULL == p_item)
    //{
    //    printf("Get software_version item failed\r\n");
    //    return -2;
    //}
    //sscanf(p_item->valuestring, "%d.%d.%d", &(dev_info->software_version[0]), 
    //            &(dev_info->software_version[1]), &(dev_info->software_version[2]));
    
    p_item = cJSON_GetObjectItem(p_root, "power_threshold");
    if (NULL == p_item)
    {
        printf("Get power_threshold item failed\r\n");
        return -2;
    }
    dev_info->power_threshold = p_item->valueint;
    
    p_item = cJSON_GetObjectItem(p_root, "detect_action");
    if (NULL == p_item)
    {
        printf("Get detect_action item failed\r\n");
        return -2;
    }
    dev_info->detect_action = p_item->valueint;
    
    p_item = cJSON_GetObjectItem(p_root, "led_init_value");
    if (NULL == p_item)
    {
        printf("Get led_init_value item failed\r\n");
        return -2;
    }
    dev_info->led_init_value = p_item->valueint;
    
    p_item = cJSON_GetObjectItem(p_root, "bat_threshold");
    if (NULL == p_item)
    {
        printf("Get bat_threshold item failed\r\n");
        return -2;
    }
    dev_info->bat_threshold = p_item->valueint;
    
    p_item = cJSON_GetObjectItem(p_root, "relay_onoff_over_thres");
    if (NULL == p_item)
    {
        printf("Get relay_onoff_over_thres item failed\r\n");
        return -2;
    }
    dev_info->relay_onoff_over_thres = p_item->valueint;
     
    return 0;
}

cJSON *fml_config_devinfo_to_json(DEV_INFO *dev_info)
{
    cJSON *p_root = NULL;
    uint8_t sw_verion[10] = {0};

    if (dev_info == NULL)
        return NULL;
    
    p_root = cJSON_CreateObject();
    if (p_root == NULL)
    {
        printf("Create json obj failed\r\n");
        return NULL;
    }
    
    printf("Add %s:%d item to obj\r\n", "dev_addr", dev_info->dev_addr);
    cJSON_AddNumberToObject(p_root, "dev_addr", dev_info->dev_addr);

    memset(sw_verion, 0, sizeof(sw_verion));
    sprintf(sw_verion, "%d.%d.%d", dev_info->software_version[0], dev_info->software_version[1], dev_info->software_version[2]);
    printf("Add %s:%s item to obj\r\n", "software_version", dev_info->software_version);
    cJSON_AddStringToObject(p_root, "software_version", sw_verion);

    printf("Add %s:%d item to obj\r\n", "power_threshold", dev_info->power_threshold);
    cJSON_AddNumberToObject(p_root, "power_threshold", dev_info->power_threshold);
    
    printf("Add %s:%d item to obj\r\n", "detect_action", dev_info->detect_action);
    cJSON_AddNumberToObject(p_root, "detect_action", dev_info->detect_action);
    
    printf("Add %s:%d item to obj\r\n", "led_init_value", dev_info->led_init_value);
    cJSON_AddNumberToObject(p_root, "led_init_value", dev_info->led_init_value);
    
    printf("Add %s:%d item to obj\r\n", "bat_threshold", dev_info->bat_threshold);
    cJSON_AddNumberToObject(p_root, "bat_threshold", dev_info->bat_threshold);
    
    printf("Add %s:%d item to obj\r\n", "relay_onoff_over_thres", dev_info->relay_onoff_over_thres);
    cJSON_AddNumberToObject(p_root, "relay_onoff_over_thres", dev_info->relay_onoff_over_thres);
    
    return p_root;
}

uint8_t *fml_config_to_json(DEV_INFO *dev_info, OTA_INFO *ota_info)
{
    cJSON *p_root = NULL;
    cJSON *p_dev_item = NULL;
    cJSON *p_ota_item = NULL;
    uint8_t *json_str = NULL;
    
    if ((dev_info == NULL) || (ota_info == NULL))
        return NULL;
    
    p_root = cJSON_CreateObject();
    if (p_root == NULL)
    {
        printf("Create json obj failed\r\n");
        return NULL;
    }
    
    p_dev_item = fml_config_devinfo_to_json(dev_info);
    if (p_dev_item == NULL)
    {
        printf("Create dev_info json obj failed\r\n");
        goto free_mem;
    }
    
    cJSON_AddItemToObject(p_root, DEV_INFO_KEY, p_dev_item);
    p_ota_item = fml_ota_otainfo_to_json(ota_info);
    if (p_ota_item == NULL)
    {
        printf("Create ota_info json obj failed\r\n");
        goto free_mem;
    }
    
    cJSON_AddItemToObject(p_root, OTA_INFO_KEY, p_ota_item);
    
    json_str = cJSON_Print(p_root);
    if (json_str == NULL)
    {
        printf("Create ota_info json string fail\r\n");
        goto free_mem;
    }
    
    printf("%s\r\n", json_str);

free_mem:
    if (p_root)
        cJSON_Delete(p_root);
    
    return json_str;
}

int32_t fml_config_from_json(const uint8_t *json_str, DEV_INFO *dev_info, OTA_INFO *ota_info)
{
    cJSON *p_root = NULL;
    cJSON *p_dev_item = NULL;
    cJSON *p_ota_item = NULL;
    
    if ((json_str == NULL) || (dev_info == NULL) || (ota_info == NULL))
        return -1;
    
    p_root = cJSON_Parse(json_str);
    if (NULL == p_root)
    {
        printf("Parse config obj failed\r\n");
        return -2;
    }
    
    p_dev_item = cJSON_GetObjectItem(p_root, DEV_INFO_KEY);
    if (NULL == p_dev_item)
    {
        printf("Get p_dev_item item failed\r\n");
        return -3;
    }
    
    fml_config_json_to_devinfo(&g_dev_info, p_dev_item);
    
    p_ota_item = cJSON_GetObjectItem(p_root, OTA_INFO_KEY);
    if (NULL == p_ota_item)
    {
        printf("Get p_ota_item item failed\r\n");
        return -4;
    }
    
    return 0;
}

int32_t fml_config_set_devaddr(uint16_t dev_addr)
{
    uint8_t *p_json = NULL;
    int32_t ret = 0;
    
    g_dev_info.dev_addr = dev_addr;
    
    p_json = fml_config_to_json(&g_dev_info, &g_ota_info);
    if (p_json == NULL)
        return -2;
    
    if (hal_flash_erase(CONFIG_START_ADDR, CONFIG_SIZE) < 0)
    {
        ret = -3;
        goto out;
    }
    
    hal_flash_write(p_json, CONFIG_START_ADDR, strlen(p_json));

out:
    if (p_json)
        free(p_json);
    
    return ret;
}

int32_t fml_config_set_power_threshold(uint16_t power_threshold)
{
    uint8_t *p_json = NULL;
    int32_t ret = 0;
    
    g_dev_info.power_threshold = power_threshold;
    
    p_json = fml_config_to_json(&g_dev_info, &g_ota_info);
    if (p_json == NULL)
        return -2;
    
    if (hal_flash_erase(CONFIG_START_ADDR, CONFIG_SIZE) < 0)
    {
        ret = -3;
        goto out;
    }
    
    hal_flash_write(p_json, CONFIG_START_ADDR, strlen(p_json));

out:
    if (p_json)
        free(p_json);
    
    return ret;
}

int32_t fml_config_set_detect_action(uint8_t detect_action)
{
    uint8_t *p_json = NULL;
    int32_t ret = 0;
    
    g_dev_info.detect_action = detect_action;
    
    p_json = fml_config_to_json(&g_dev_info, &g_ota_info);
    if (p_json == NULL)
        return -2;
    
    if (hal_flash_erase(CONFIG_START_ADDR, CONFIG_SIZE) < 0)
    {
        ret = -3;
        goto out;
    }
    
    hal_flash_write(p_json, CONFIG_START_ADDR, strlen(p_json));

out:
    if (p_json)
        free(p_json);
    
    return ret;
}

int32_t fml_config_set_led_init_value(uint8_t led_init_value)
{
    uint8_t *p_json = NULL;
    int32_t ret = 0;
    
    g_dev_info.led_init_value = led_init_value;
    
    p_json = fml_config_to_json(&g_dev_info, &g_ota_info);
    if (p_json == NULL)
        return -2;
    
    if (hal_flash_erase(CONFIG_START_ADDR, CONFIG_SIZE) < 0)
    {
        ret = -3;
        goto out;
    }
    
    hal_flash_write(p_json, CONFIG_START_ADDR, strlen(p_json));

out:
    if (p_json)
        free(p_json);
    
    return ret;
}

int32_t fml_config_set_bat_threshold(uint8_t bat_threshold)
{
    uint8_t *p_json = NULL;
    int32_t ret = 0;
    
    g_dev_info.bat_threshold = bat_threshold;
    
    p_json = fml_config_to_json(&g_dev_info, &g_ota_info);
    if (p_json == NULL)
        return -2;
    
    if (hal_flash_erase(CONFIG_START_ADDR, CONFIG_SIZE) < 0)
    {
        ret = -3;
        goto out;
    }
    
    hal_flash_write(p_json, CONFIG_START_ADDR, strlen(p_json));

out:
    if (p_json)
        free(p_json);
    
    return ret;
}

int32_t fml_config_set_relay_onoff_over_thres(uint8_t onoff)
{
    uint8_t *p_json = NULL;
    int32_t ret = 0;
    
    g_dev_info.relay_onoff_over_thres = onoff;
    
    p_json = fml_config_to_json(&g_dev_info, &g_ota_info);
    if (p_json == NULL)
        return -2;
    
    if (hal_flash_erase(CONFIG_START_ADDR, CONFIG_SIZE) < 0)
    {
        ret = -3;
        goto out;
    }
    
    hal_flash_write(p_json, CONFIG_START_ADDR, strlen(p_json));

out:
    if (p_json)
        free(p_json);
    
    return ret;
}